#ifndef _NE_UI_OBJECT_H_
#define _NE_UI_OBJECT_H_

#include <UI/UIDefine.h>

namespace ne
{
    class UIWindow;

    class NEAPI UIObject : public Node, public RenderableObject
    {
        friend class UIWindow;
        friend class UIManager;

        public:
            explicit UIObject(const std::string &name="UIObject");

            UIWindow* getWindow() const;

            void setID(uint32_t id);
            uint32_t getID() const;

            // Get Local Axes in TS_WORLD
            Vector3 getXAxis() const { return convertLocalToWorldVector(Vector3::UNIT_X); }
            Vector3 getYAxis() const { return convertLocalToWorldVector(Vector3::UNIT_Y); }
            Vector3 getZAxis() const { return convertLocalToWorldVector(Vector3::UNIT_Z); }

            // Size
            virtual void setSize(const Vector2 &v);
            virtual Vector2 getSize() const;
            virtual void setSize(const real width, const real height);
            virtual void getSize(real &width, real &height) const;

            virtual void setWidth(const real width);
            virtual real getWidth() const;

            virtual void setHeight(const real height);
            virtual real getHeight() const;

            // Color
            virtual void setColor(const Color &color);
            virtual Color getColor() const;

            virtual void setAlpha(const real alpha);
            virtual real getAlpha() const;

            virtual void setAlignType(const UIAlignType align);
            virtual UIAlignType getAlignType() const;
            const Vector3& getAlignPosition() const;

            virtual void setSprite(const std::string &name);
            virtual const std::string& getSprite() const;

            // Enable
            virtual void setEnable(const bool b);
            virtual void setEnableRecursively(const bool b);
            // Visible
            virtual void setVisible(const bool b);
            virtual void setVisibleRecursively(const bool b);
            // Active
            virtual void setActive(const bool b);
            virtual void setActiveRecursively(const bool b);

            virtual bool isMouseOver() const;
            virtual bool isMouseButtonDown(const MouseButton) const;

            virtual ~UIObject();

        protected:
            virtual void _updateFromParent(const bool parentHasChanged=false) const;

            virtual void _updateAlignPosition() const;

            virtual bool _updateSelf();
            virtual bool _updateAll();

            virtual bool _renderSelf();
            virtual bool _renderAll();

            virtual void _genAtlasGeometry(const DynamicGeometryPtr &pGeometry, const AtlasPtr &pAtlas);

            virtual UIObject* _detected(const Ray &ray);

            // Call back functions
            virtual void _onResized(const Vector2 &v);

            // Mouse Event
            virtual void _onMouseOver(const MouseEvent &event);
            virtual void _onMouseOut(const MouseEvent &event);
            virtual void _onMouseMove(const MouseEvent &event);
            virtual void _onMouseWheel(const MouseEvent &event);
            virtual void _onMouseButtonUp(const MouseEvent &event);
            virtual void _onMouseButtonDown(const MouseEvent &event);
            virtual void _onMouseButtonDrag(const MouseEvent &event);
            virtual void _onMouseClicked(const MouseEvent &event);
            virtual void _onMouseDoubleClicked(const MouseEvent &event);

            // Keyboard Event
            virtual void _onKeyUp(const KeyboardEvent &event);
            virtual void _onKeyDown(const KeyboardEvent &event);
            virtual void _onCharacter(const uint32_t character);

            virtual void _onEnabled();
            virtual void _onDisabled();

            virtual void _onShown();
            virtual void _onHidden();

            virtual void _onActived();
            virtual void _onDeactived();

        private:
            UIObject(const UIObject &);

            UIObject& operator = (const UIObject &);

        protected:
            uint32_t mID;
            real mWidth;
            real mHeight;
            Color mColor;
            UIAlignType mAlignType;
            mutable Vector3 mAlignPosition;
            std::string mSpriteName;

            bool mMouseOver;
            uint32_t mMouseButtonsDown;
    };
}

#endif
